# Simulation enviroment
import os
import pygame as pg
from ombot import ground
from ombot import staticObject
from ombot import robot
# import ground
# import staticObject
# import robot

pg.init()
pg.font.init()
font = pg.font.SysFont('Times New Roman', 10)
color = pg.Color('dodgerblue2')


class World:
    def __init__(self, win):
        # display
        self.win = win
        # self.display = display

        # ground
        self.ground = ground.Ground(win)
        # self.ground = ground.Ground(display)

        # static objects: obs
        self.n_obs = 0
        self.obs = []
        self.createObs()

        # moving objects: robot
        self.robot = robot.Robot(win)
        # self.robot = robot.Robot(display)

        # x of the screen boundary
        self.show_x = self.robot.x - 11

    def createObs(self, n_obs=2):
        self.WIDTH = 10
        self.HEIGHT = 15
        self.MIN_DISTANCE = 150

        self.n_obs = n_obs
        self.obs.clear()

        last_obs_x = 20  # first obs pos
        for o in range(self.n_obs):
            r = int.from_bytes(os.urandom(1), 'big')
            current_x = last_obs_x + self.MIN_DISTANCE + r % 10
            current_y = self.ground.ground_level - int(self.HEIGHT / 2) + r % 5
            self.obs.append(
                staticObject.StaticObject(self.win, current_x, current_y, self.WIDTH + r % 30, self.HEIGHT, o))
            last_obs_x = current_x

    def reset(self):
        # reset ground
        self.ground.reset()

        # delete old obs, create new obs
        self.createObs()

        # reset robot
        self.robot.reset()

    def update(self):
        # update robot
        self.robot.update()

        # update x of boundary
        self.show_x = self.robot.x - 11

        # update groud line
        self.ground.update(self.show_x)

        # update obs
        for o in range(self.n_obs):
            self.obs[o].update(self.show_x)

        # dectection collision
        self.collision()

        # update distance sensor
        self.measure()

    # # robot desicion
    # self.robot.think()

    def show(self):
        self.ground.show(self.show_x)

        for o in range(self.n_obs):
            self.obs[o].show(self.show_x)

        self.robot.show(self.show_x)

    def collision(self):
        self.robot.collision = -1
        for o in range(self.n_obs):
            if ((abs(self.robot.x - self.obs[o].x) < (self.robot.width // 2 + self.obs[o].width // 2)) and \
                    (abs(self.robot.y - self.obs[o].y) < (self.robot.height // 2 + self.obs[o].height // 2))):
                self.robot.collision = o
                self.robot.n_collisions += 1
                return True
        return False

    def measure(self):
        self.robot.obs = -1
        self.robot.distance = 10.0
        for o in range(self.n_obs):
            diff = (self.obs[o].x - self.robot.x) / 100
            if (diff > 0 and diff < self.robot.distance):
                self.robot.distance = diff
                self.robot.obs_width = self.obs[o].width / 100
                self.robot.obs = o
        # print(self.robot.obs, self.robot.distance)
        return self.robot.distance, self.robot.obs_width
